
//解包
module DataParser {
	var dataBuffer: ArrayBuffer = null;
	var dataView: DataView = null;
	var offset: number = 0;
	var leng: number = 0;
	let packethead = [
		["cbCheckCode", "BYTE"],
		["cbVersion", "BYTE"],
		["wPacketSize", "WORD"],
		["mainCmd", "WORD"],
		["subCmd", "WORD"]];

	//外部访问此方法
	export function WSReceiveMsg(RegData: any, databuffer: ArrayBuffer) {
		let AllBuffer = new Uint8Array(databuffer)
		let boydataCompress = new Uint8Array(AllBuffer.byteLength - 8)
		let unAllCompressdata: Int8Array = null
		for (let i = 8; i < AllBuffer.byteLength; i++) {
			boydataCompress[i - 8] = AllBuffer[i]
		}
		if (boydataCompress.byteLength > 0) {
			unAllCompressdata = new Uint8Array(boydataCompress.byteLength + 8)
			for (let i = 0; i < unAllCompressdata.byteLength; i++) {
				if (i < 8) {
					unAllCompressdata[i] = AllBuffer[i]
				} else {
					unAllCompressdata[i] = boydataCompress[i - 8]
				}
			}
		} else {
			unAllCompressdata = new Uint8Array(databuffer)
		}
		let UnCompressBuffer = unAllCompressdata.buffer

		dataBuffer = UnCompressBuffer;
		dataView = new DataView(dataBuffer);
		offset = 0;
		leng = dataBuffer.byteLength

		let Headdata = parse(packethead, null, null, );

		let keytable = FindMessageID(RegData, Headdata["mainCmd"], Headdata["subCmd"]);
		let boydata = parse(keytable, Headdata["mainCmd"], Headdata["subCmd"]);
		let obj = {
			mainCmd: Headdata["mainCmd"],
			subCmd: Headdata["subCmd"],
			msgData: boydata
		}
		return obj;
	}
	function FindMessageID(RegData: any, mainCmd: number, subCmd: number) {
		if (mainCmd == null || subCmd == null) {
			return
		}
		let SmainID = mainCmd.toString();
		let SsubID = subCmd.toString();
		if (RegData.MainCMD_MsgId.hasOwnProperty(SmainID)) {
			let Mainmsgtable = RegData.MainCMD_MsgId[SmainID]
			if (Mainmsgtable.hasOwnProperty(SsubID)) {
				return Mainmsgtable[SsubID]
			}
		}
	}
	function parse(structArray, mainID = null, subID = null) {
		let parseData = {};
		//info[0] key
		//info[1] 类型
		//info[2] 数组大小
		if (structArray == null) {
			return
		}
		try {
			for (let i = 0; i < structArray.length; i++) {
				let info = [].concat(structArray[i]);
				if (offset >= dataBuffer.byteLength) {
					return parseData
				}
				if (!!info) {
					// console.log(info[1])
					switch (info[1]) {
						case "LONG":
							parseData[info[0]] = readDWord();
							break;
						case "DLONG":
							parseData[info[0]] = readDLONG();
							break;
						case "INT":
							parseData[info[0]] = readInt();
							break;
						case "DWORD":
							parseData[info[0]] = readDWord();
							break;
						case "WORD":
							parseData[info[0]] = readWord();
							break;
						case "FLOAT":
							parseData[info[0]] = readFloat();
							break;
						case "FLOAT[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readFloat();
							}
							break;
						case "DOUBLE":
							parseData[info[0]] = readDouble();
							break;
						case "INT[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readInt();
							}
							break;
						case "DWORD[]":
							parseData[info[0]] = [];

							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readDWord();
							}
							break;
						case "WORD[]":
							parseData[info[0]] = [];
							if (info[2] == 0) {
								info[2] = parseData["wRecordNumber"]
							}
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readWord();
							}
							break;
						case "WORD[][]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readWordArray(info[3]);
							}
							break;
						case "BYTE":
							parseData[info[0]] = readByte();
							break;
						case "BOOL":
							parseData[info[0]] = readByte() != 0;
							break;
						case "BOOLEAN":
							parseData[info[0]] = readBoolean();
							break;
						case "BOOL[]":
						case "BOOLEAN[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readBoolean();
							}
							break;
						case "BYTE[]":

							if (info[2] == 0 && parseData["cbCardCount"]) {
								info[2] = parseData["cbCardCount"]
							}
							parseData[info[0]] = readByteArray(info[2]);
							break;
						case "BYTE[][]":
							parseData[info[0]] = readByteArray2(info[2], info[3]);
							break;
						case "INT[][]":
							parseData[info[0]] = readIntArray2(info[2], info[3]);
							break;
						case "TCHAR":
							parseData[info[0]] = readCharArray(info[2]);
							break;
						case "TCHARZ":
							parseData[info[0]] = readCharArrayS(info[2]);
							break;
						case "CHAR":
							parseData[info[0]] = readChar();
							break;
						case "CHAR[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readChar();
							}
							break;
						case "CHARS":
							parseData[info[0]] = readCharArray(info[2]);
							break;
						case "CHINESE":
							parseData[info[0]] = readCharChineseArray(info[2]);
							break;
						case "CHARSCHINESE[]":
							parseData[info[0]] = readCharChineseArray2(info[2], info[3]);
							break;

						case "TCHARS":
							parseData[info[0]] = readTCharArray(info[2]);
							break;
						case "TCHARS[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readTCharArray(info[3]);
							}
							break;
						case "CHARS[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readCharArray(info[3]);
							}
							break;
						case "SCORE":
						case "DLONG[]":
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readDLONG();
							}
							break;
						case "INT64_NUMBER":
							parseData[info[0]] = readInt64Number();
							break;
						case "SCORE[]":
						case "DLONG[][]":
							parseData[info[0]] = readDlongArray2(info[2], info[3]);
							break;
						case "INT64_NUMBER[]":
							parseData[info[0]] = readInt64NumberArray(info[2]);
							break;
						case "SCORE[][]":
						case "LONGLONG[][]":
						case "INT64_NUMBER[][]":
							//parseData[info[0]] = readInt64NumberArray(info[2]);
							parseData[info[0]] = [];
							for (let j = 0; j < info[2]; j++) {
								parseData[info[0]][j] = readInt64NumberArray(info[3]);
							}
							break;
						case "INT64_BUFFER":
							parseData[info[0]] = readInt64Buffer();
							break;
						case "STRUCT":
							parseData[info[0]] = parse(info[2]);
							break;
						case "STRUCTBYTE":
							for (let i = 0; i < ((leng - 8) / 3); i++) {
								let a = readByte();
								let b = readByte();
								let c = readByte();
								parseData[info[0]][i] = [a, b, c]
							}
							break;
						case "SPSTRUCT":
						// console.log("包长",leng)
							parseData[info[0]] = parse(info[2]);
							// console.log(leng, offset)
							while ((leng - offset) > 8) {
								let wDataSize = Number(readWord());		//数据大小
								// console.log(wDataSize)
								if (wDataSize > 0) {
									let wDataDescribe = Number(readWord());	//数据描述
									// console.log(wDataDescribe)
									switch (wDataDescribe) {
										case 10:
											let nickName = readCharArray(wDataSize / 2)
											parseData[info[0]]["nickName"] = nickName;
											break;
										case 11:
											let groupName = readCharArray(wDataSize / 2)
											break;
										case 12:
											let underWrite = readCharArray(wDataSize / 2)
											break;
										case 13:
											let userAddress = readCharArray(wDataSize / 2)
											break;
										case 14:
											let mobileNum = readCharArray(wDataSize / 2)
											break;
										case 15:
											let cityName = readCharArray(wDataSize / 2);
											parseData[info[0]]["nickName"] = `${parseData[info[0]]["nickName"]}-${cityName}`
											break;
										default:
											break;
									}
								}
								else {
									break;
								}
							}
							break;
						case "STRUCT[]":
							parseData[info[0]] = [];
							info[3] = parseData["fish_count"] || parseData["iFishCount"] || parseData["cbHuCount"] || parseData["ItemBetAmountNum"] || parseData["wUserCount"] || parseData["wCount"] || parseData["cbCount"] || parseData["wSpreadCount"] || parseData["wSpreadCount"] || parseData["cbPayCount"] || parseData["wServerCount"] || parseData["wGameCount"] || parseData["wRoomCount"] || info[3]
							// for (let i = 0; i < ((leng - 8) / 183); i++) {
							// 	parseData[info[0]][i] = parse(info[2]);
							// }
							let j = 0;
							// console.log(leng, offset)
							while ((leng - offset) > 0) {
								parseData[info[0]][j] = parse(info[2]);
								if(parseData[info[0]][j]["szCityName"] == ""&&parseData[info[0]][j]["lTakeMinScore"] === 0){
									parseData[info[0]].splice(parseData[info[0]].length-1,1);
									break;
								}
								j++
							}
							break;
						case "STRUCT[][]":
							parseData[info[0]] = [];
							let ret = [];
							for (let k = 0; k < info[3]; k++) {
								ret[k] = [];
								for (let j = 0; j < info[4]; j++) {
									ret[k][j] = parse(info[2]);

								}
							}
							parseData[info[0]] = ret;
							break;
						case "SYSTEMTIME":
							parseData[info[0]] = parse([
								["wYear", "WORD"],
								["wMonth", "WORD"],
								["wDayOfWeek", "WORD"],
								["wDay", "WORD"],
								["wHour", "WORD"],
								["wMinute", "WORD"],
								["wSecond", "WORD"],
								["wMilliseconds", "WORD"]
							]);
							break;
						default:
							throw new Error(info[1] + ":undefined "); //使用这种方式报错能够终止后续代码继续运行
					}
				}
			}
		} catch (err) {
			// console.log("解包失败，mainID:" + mainID + ",subID:" + subID);
			return
		}
		return parseData;
	}


	function isLittleEndian() {
		let buffer = new ArrayBuffer(2);
		new DataView(buffer).setInt16(0, 256, true);
		return new Int16Array(buffer)[0] === 256;
	}
	function getOffset() {
		return offset;
	}
	function readDLONG() {
		let ret = 0;
		let v1 = dataView.getUint8(offset++);
		let v2 = dataView.getUint8(offset++);
		let v3 = dataView.getUint8(offset++);
		let v4 = dataView.getUint8(offset++);
		let v5 = dataView.getUint8(offset++);
		let v6 = dataView.getUint8(offset++);
		let v7 = dataView.getUint8(offset++);
		let v8 = dataView.getUint8(offset++);
		let negative = false;
		if (v8 >= 128) {
			negative = true;
			v1 = v1 ^ 0xff;
			v2 = v2 ^ 0xff;
			v3 = v3 ^ 0xff;
			v4 = v4 ^ 0xff;
			v5 = v5 ^ 0xff;
			v6 = v6 ^ 0xff;
			v7 = v7 ^ 0xff;
			v8 = v8 ^ 0xff;
		}
		ret = ret + v1;
		ret = ret + v2 * (0xff + 1);
		ret = ret + v3 * (0xffff + 1);
		ret = ret + v4 * (0xffffff + 1);
		ret = ret + v5 * (0xffffffff + 1);
		ret = ret + v6 * (0xffffffffff + 1);
		ret = ret + v7 * (0xffffffffffff + 1);
		ret = ret + v8 * (0xffffffffffffff + 1);
		if (negative == true) {
			ret = -(ret + 1);
		}
		return ret;
	}
	function readInt() {
		let ret = dataView.getInt32(offset, isLittleEndian());
		offset += 4;
		return ret;
	}
	function readWord() {
		let ret = 0;
		ret = ret + dataView.getUint8(offset++);
		ret = ret + dataView.getUint8(offset++) * (0xff + 1);
		return ret;
	}
	function readDWord() {
		let ret = 0;
		ret = ret + dataView.getUint8(offset++);
		ret = ret + dataView.getUint8(offset++) * (0xff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffff + 1);
		return ret;
	}
	function readFloat() {
		let ret = dataView.getFloat32(offset, isLittleEndian());
		offset += 4;
		return ret;
	}
	function readDouble() {
		let ret = 0;
		ret = dataView.getUint8(offset++);
		ret = ret + dataView.getUint8(offset++) * (0xff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffffffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffffffffff + 1);
		ret = ret + dataView.getUint8(offset++) * (0xffffffffffffff + 1);
		return ret;
	}
	function readByte() {
		let ret = dataView.getUint8(offset++);
		return ret;
	}
	function readBoolean() {
		let value = dataView.getUint8(offset);
		offset += 1;
		let ret = false;
		if (value == 1) {
			ret = true;
		}
		return ret;
	}
	function readChar() {
		let ret = "";
		let value = dataView.getUint8(offset);
		offset += 1;
		ret = String.fromCharCode(value);
		return ret;
	}
	function readTChar() {
		let ret = "";
		let value = dataView.getUint16(offset, isLittleEndian());
		offset += 2;
		ret = String.fromCharCode(value);
		return ret;
	}
	function readCharArray(len) {
		let ret = "";
		let _vLen = offset + len;
		for (let i = 0; i < len; i++) {
			let vCode = 0;
			vCode = vCode + dataView.getUint8(offset++);
			vCode = vCode + dataView.getUint8(offset++) * (0xff + 1);
			if (vCode > 0) {
				ret += String.fromCharCode(vCode);
			}
		}
		return ret;
	}
	function readCharArrayS(len) {
		let ret = "";
		for (let i = 0; i < len; i++) {
			let vCode = 0;
			vCode = vCode + dataView.getUint8(offset++);
			vCode = vCode + dataView.getUint8(offset++) * (0xff + 1);
			if (vCode > 0) { ret += String.fromCharCode(vCode); }
			else if (vCode == 0) {
				return ret;
			}
			return ret;
		}
	}
	function IsLess127(num: number) {
		if (num <= 127) {
			return true
		}
		return false
	}
	function readCharChineseArray(len) {
		let ret = "";
		//let Str = ["C4E3","BAC3"];
		let sStr = "";
		let offse = offset;
		let values = []
		for (let i = 0; i < len / 2; i++) {

			let value = dataView.getUint8(offse)
			if (value > 127) {
				let valuechinese = dataView.getUint16(offse, isLittleEndian());
				offse += 2
				values.push(valuechinese)
			} else {
				values.push(value)
				offse += 1
			}

			if (value !== 0) {
				// if (cc.sys.os == cc.sys.OS_WINDOWS) {
				// 	ret += String.fromCharCode(value);
				// } else {
				ret += String.fromCharCode(value);
				// }
			} else {
				values.pop()
				let myUrl: Url = new Url();
				let aa = myUrl.decode(values);
				ret = aa
				break;
			}
		}
		offset += len * 1;
		return ret;
	}
	function hexCharCodeToStr(hexCharCodeStr) {
		let trimedStr = hexCharCodeStr.trim();
		let rawStr =
			trimedStr.substr(0, 2).toLowerCase() === "0x"
				?
				trimedStr.substr(2)
				:
				trimedStr;
		let len = rawStr.length;
		if (len % 2 !== 0) {
			alert("Illegal Format ASCII Code!");
			return "";
		}
		let curCharCode;
		let resultStr = [];
		for (let i = 0; i < len; i = i + 2) {
			curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
			resultStr.push(String.fromCharCode(curCharCode));
		}
		return resultStr.join("");
	}

	function readCharChineseArray2(len1, len2) {
		let ret = [];
		let i;
		for (i = 0; i < len1; i++) {
			ret[i] = [];
			ret[i] = readCharChineseArray(len2);
		}
		return ret;
	}
	function readCharArray2(len1, len2) {
		let ret = [];

		let i;
		let j;
		for (i = 0; i < len1; i++) {
			ret[i] = [];

			for (j = 0; j < len2; j++) {
				ret[i][j] = readCharArray(len2);
			}
		}

		return ret;
	}
	function readTCharArray(len) {
		let ret = "";
		let offse = offset;
		for (let i = 0; i < len; i++) {
			let value = dataView.getUint16(offse, isLittleEndian());
			offse += 2;
			if (value != 0) {
				/*if(cc.sys.os == cc.sys.OS_WINDOWS){
					ret += cc.vv.MyUtil.utf16to8(String.fromCharCode(value));
				}else{*/
				ret += String.fromCharCode(value);
				//}
			} else {
				break;
			}
		}
		offset += len * 2;
		return ret;
	}

	function readInt64Number() {
		let ret = 0;
		let dWord1 = readDWord();
		let dWord2 = readDWord();
		if (isLittleEndian()) {
			//负数
			if (dWord2 >= 0x80000000) {
				dWord1 = ~dWord1;
				dWord1 = dWord1 >>> 0;
				dWord2 = ~dWord2;
				ret = 0 - (dWord2 * Math.pow(2, 32) + dWord1 + 1);
			} else {
				ret = dWord2 * Math.pow(2, 32) + dWord1;
			}
		} else {
			//负数
			if (dWord1 >= 0x80000000) {
				dWord1 = ~dWord1;
				dWord2 = ~dWord2;
				dWord2 = dWord2 >>> 0;
				ret = 0 - (dWord1 * Math.pow(2, 32) + dWord2 + 1);
			} else {
				ret = dWord1 * Math.pow(2, 32) + dWord2;
			}
		}

		return ret;
	}
	//return [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
	function readInt64Buffer() {
		let rets = [];
		let i;

		for (i = 0; i < 8; i++) {
			let ret = readByte();

			if (isLittleEndian()) {
				rets.unshift(ret);
			} else {
				rets.push(ret);
			}
		}

		return rets;
	}
	function redLong() {
		let rets = [];
		let i;

		for (i = 0; i < 8; i++) {
			let ret = readByte();

			if (isLittleEndian()) {
				rets.unshift(ret);
			} else {
				rets.push(ret);
			}
		}

		return rets;
	}
	function readByteArray(len) {
		let ret = [];

		let i;
		for (i = 0; i < len; i++) {
			ret[i] = readByte();
		}
		return ret;
	}

	function readDlongArray2(len1, len2) {
		let ret = [];

		let i;
		let j;
		for (i = 0; i < len1; i++) {
			ret[i] = [];
			for (j = 0; j < len2; j++) {
				ret[i][j] = readDLONG();
			}
		}

		return ret;
	}

	function readByteArray2(len1, len2) {
		let ret = [];

		let i;
		let j;
		for (i = 0; i < len1; i++) {
			ret[i] = [];

			for (j = 0; j < len2; j++) {
				ret[i][j] = readByte();
			}
		}

		return ret;
	}

	function readInt64NumberArray(len) {
		let ret = [];

		let i;
		for (i = 0; i < len; i++) {
			ret[i] = readInt64Number();
		}

		return ret;
	}
	function readIntArray2(len1, len2) {
		let ret = [];

		let i;
		let j;
		for (i = 0; i < len1; i++) {
			ret[i] = [];
			for (j = 0; j < len2; j++) {
				ret[i][j] = readInt();
			}
		}

		return ret;
	}

	function readWordArray(len) {
		let ret = [];

		let i;
		for (i = 0; i < len; i++) {
			ret[i] = readWord();
		}

		return ret;
	}



}


